﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Device.Location;
using System.Threading;
using System.ComponentModel;
using Microsoft.Phone.Shell;
using System.IO.IsolatedStorage;
using System.IO;

namespace StravaUploader
{
    
    public partial class MainPage :  PhoneApplicationPage
    {
        static public String message; 
        public Boolean ready;
        static public GeoCoordinateWatcher watcher;
        static public String authJSON;
        public double latitude;
        public double longtitude;
        private BackgroundWorker loggingThread;

        private String stravaToken;

        private static bool hasSeenIntro;
        private static string StravaFileName;



        // Constructor
        public MainPage()
        {
            if (watcher == null)
            {
                watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
                watcher.MovementThreshold = 10;
                watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);
                watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);
                watcher.Start();
            }

            InitializeComponent();

            // Set the data context of the listbox control to the sample data
            DataContext = App.ViewModel;
            this.Loaded += new RoutedEventHandler(MainPage_Loaded);

            

            GPSHelper.log = new LinkedList<GeoPosition<GeoCoordinate>>();
            loggingThread = new BackgroundWorker();
            loggingThread.WorkerSupportsCancellation = true;
            loggingThread.DoWork += new DoWorkEventHandler(LogCoordinates);

            //User should be informed about fact tha application will run in background.
            PhoneApplicationService.Current.ApplicationIdleDetectionMode = IdleDetectionMode.Disabled;
            StravaFileName = "strava.properties";
            
        }

        // Load data for the ViewModel Items
        private void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            if (!App.ViewModel.IsDataLoaded)
            {
                App.ViewModel.LoadData();
            }

            if (!HasUserSeenIntro())
            {
                MessageBox.Show("The application will continue run even screen is locked. This may consume battery extra.", "Run in background", MessageBoxButton.OK);
            }
        }


        void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
        {
            switch (e.Status)
            {
                case GeoPositionStatus.Disabled:
                    // The Location Service is disabled or unsupported.
                    // Check to see whether the user has disabled the Location Service.
                    if (watcher.Permission == GeoPositionPermission.Denied)
                    {
                        // The user has disabled the Location Service on their device.
                        message = "you have this application access to location.";
                    }
                    else
                    {
                        message = "location is not functioning on this device";
                    }
                    break;

                case GeoPositionStatus.Initializing:
                    // The Location Service is initializing.
                    // Disable the Start Location button.
                    ready = false;
                    break;

                case GeoPositionStatus.NoData:
                    // The Location Service is working, but it cannot get location data.
                    // Alert the user and enable the Stop Location button.
                    message = "location data is not available.";
                    ready = true;
                    break;

                case GeoPositionStatus.Ready:
                    // The Location Service is working and is receiving location data.
                    // Show the current position and enable the Stop Location button.
                    message = "location data is available.";
                    ready = true;
                    break;
            }

            System.Diagnostics.Debug.WriteLine("INFO: " + message);
            this.GPSStatus.Text = message;
        }

        void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            latitude = e.Position.Location.Latitude;
            longtitude = e.Position.Location.Longitude;

            System.Diagnostics.Debug.WriteLine("INFO: Current coordinates are: " + latitude + ", " + longtitude);


        }

        private void StartStop_Click(object sender, RoutedEventArgs e)
        {
            StateHolder.Started = !StateHolder.Started;
            if(!finishButton.IsEnabled)
                finishButton.IsEnabled = true;
            if (StateHolder.Started)
            {
                loggingThread.RunWorkerAsync();
                StartStop.Content = "Pause";
            }
            else
            {
                StartStop.Content = "Start";
                
            }
        }

        private void LogCoordinates(object o, DoWorkEventArgs e)
        {

            while (StateHolder.Started)
                {
                    if(((BackgroundWorker)o).CancellationPending)
                    {
                        return;
                    }
                    if (!watcher.Position.Location.Speed.ToString().Equals("NaN"))
                    {
                        GPSHelper.log.AddLast(watcher.Position);
                        System.Diagnostics.Debug.WriteLine("log added: " + watcher.Position.Location + ", speed = " + watcher.Position.Location.Speed);
                        System.Diagnostics.Debug.WriteLine("log size: " + GPSHelper.log.Count);
                        message = "Signal OK";
                    }
                    else
                    {
                        message = "Signal lost";
                        System.Diagnostics.Debug.WriteLine("INFO: Signal lost");
                    }
                    Thread.Sleep(1000);
                }
        }


        private void button1_Click(object sender, RoutedEventArgs e)
        {
            if (!StateHolder.LoginDone || stravaToken == null)
            {
                NavigationService.Navigate(new Uri("/Login.xaml", UriKind.Relative));
                stravaToken = StravaCommunicator.token;
            }

        }


        private void Panorama_Loaded(object sender, RoutedEventArgs e)
        {
            if (StateHolder.LoginDone)
            {
                this.LoginToStravaButton.Visibility = System.Windows.Visibility.Collapsed;
                this.StartStop.IsEnabled = true;
            }
            else
            {
                this.StartStop.IsEnabled = false;
            }


            if (StateHolder.Started)
            {
                this.finishButton.IsEnabled = true;
            }
            else
            {
                this.finishButton.IsEnabled = false;
            }


            this.GPSStatus.Text = message;
        }

        private void finishButton_Click(object sender, RoutedEventArgs e)
        {
            loggingThread.WorkerSupportsCancellation = true;
            loggingThread.CancelAsync();
            StartStop.Content = "Start";
            NavigationService.Navigate(new Uri("/UploadToStravaCom.xaml", UriKind.Relative));
        }

        /// <summary>Will return false only the first time a user ever runs this.
        /// Everytime thereafter, a placeholder file will have been written to disk
        /// and will trigger a value of true.</summary>
        public static bool HasUserSeenIntro()
        {
            if (hasSeenIntro) return true;

            using (var store = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (!store.FileExists(StravaFileName))
                {
                    
                    using (var stream = store.OpenFile(StravaFileName, FileMode.Create))
                    {
                        stream.Write(new byte[] { 1 }, 0, 1);
                    }
                    return false;
                }

                hasSeenIntro = true;
                return true;
            }
        }

    }
}